<?php

namespace Logic;


use Config\mysql;

class PraiseLogic
{

    /**
     * 验证该用户是否可以领取CDK
     * @param $user
     * @return int|mixed
     */
    public function validateCdk($user)
    {
        $canReceive = $user['is_reveive_cdk'] ?? 0;
        return $canReceive; //1:已经领取过CDK;
    }

    /**
     * 验证该用户是否完成任务
     * @param $user
     * @return int
     */
    public function validateTask($user)
    {
        $redis = RedisClientLogic::getInstance();
        //获取我的总点赞数
        $myTotalGivePraise = $redis->hGet(TOTAL_MY_DIANZAN, $user['uid']);
        $mySendWishs = $user['my_wish_id'] ?? 0;
        if ($myTotalGivePraise && $myTotalGivePraise >= GIVE_PRIZE_ACHIEVE && ($mySendWishs != 0)) { //总点赞数超过20,并且发送过祝福语表示完成任务
            return 1; //完成任务
        }
        return 0; //还未完成任务
    }


    /**
     * 进行点赞
     * @param $user
     * @param $wish_id
     * @return array
     */
    public static function givePrize($user, $wishId, $thisPraiseKey)
    {
        $redis = RedisClientLogic::getInstance();
        //进行点赞
        $res = $redis->sAdd($thisPraiseKey, $user['uid']); //将该用户添加到该条祝福语点赞用户id中
        if (($res <=> 0) === 0) {
            return ['res' => -1, 'msg' => '您已经点赞了这条祝福语，不能重复点赞哦!'];
        }
        $redis->zIncrBy(ORDER_WISHES, 1, $wishId);//祝福语点赞数+1
        $todayNumKey = TODAY_MY_DIANZAN . ':' . date('Y-m-d');
        $num = $redis->zIncrBy($todayNumKey, 1, $user['uid']);
        if (($num <=> PER_DAY_LIMIT_GIVE_PRIZE) === 1) { //当日点赞数超限
            $redis->zIncrBy(ORDER_WISHES, -1, $wishId);
            $redis->hIncrBy($todayNumKey, -1, $user['uid']);
            return ['res' => 0, 'msg' => '您今日点赞已达上限，不能再点赞了哦!'];
        }
        $redis->expire($todayNumKey, 172800);//设置两天过期
        $redis->hIncrBy(TOTAL_MY_DIANZAN, $user['uid'], 1);//增加我的点赞数
        //存储到点赞记录表中
        $createTime = date('Y-m-d H:i:s');
        try {
            $sql = "INSERT INTO `tbPraiseLog` ( `wish_id`,`uid`,`create_time`) values(:wish_id,:uid,:times)";
            $dbLink = mysql::mysql();
            $st = $dbLink->prepare($sql);
            $row = $st->execute([':wish_id' => $wishId, ':uid' => $user['uid'], ':times' => $createTime]);
            if ($row) {
                return ['res' => 0, 'msg' => '点赞成功!'];
            }
            throw new \PDOException("failed!");
        } catch (\PDOException $e) {
            $redis->sRem($thisPraiseKey, $user['uid']);
            $redis->zIncrBy(ORDER_WISHES, -1, $wishId);
            $redis->zIncrBy($todayNumKey, -1, $user['uid']);
            $redis->hIncrBy(TOTAL_MY_DIANZAN, $user['uid'], -1);
            return ['res' => -1, 'msg' => '点赞失败!' . $e->getMessage(), []];
        }
    }

    /**
     * 领取CDK
     * @param $token
     * @param $user
     * @return array
     */
    public static function provideCdk($token, $user)
    {
        $redis = RedisClientLogic::getInstance();
        //总的领取的CDK的用户数量
        $totalReveiveKey = TOTAL_CDK_GRANT_TO_USER;
        $reveiveNum = $redis->sCard($totalReveiveKey);
        //活动截止到当天应该发放的总的CDK数量
        $totalNum = self::getCdkTotalNum();
        if ($reveiveNum >= $totalNum) {
            return ['res' => -1, 'msg' => '今日CDK已发放完毕，请明日再来兑换!', 'data' => []];
        }
        $reveive = $redis->sAdd($totalReveiveKey, $user['uid']);
        if ($reveive === 0) {
            $redis->hSet($token, 'is_reveive_cdk', 1); //redis更新为已领取
            //该用户已经领取过CDK
            return ['res' => -1, 'msg' => '您已经领取过CDK，活动期间只能领取一次哦!', 'data' => []];
        }
        $reveiveNum = $redis->sCard($totalReveiveKey);
        if (($reveiveNum <=> $totalNum) === 1) { //领取数超过总数
            $redis->sRem($totalReveiveKey, $user['uid']);
            return ['res' => -1, 'msg' => '今日CDK已发放完毕，请明日再来兑换!', 'data' => []];
        }
        //更新该数据库用户为CDK已领取
        try {
            $dbLink = mysql::mysql();
            $uid = $user['uid'];
            $cdk = self::createCdkString();
            $sql = "update `tbUser` set is_reveive_cdk = 1,cdk = '$cdk' where uid = '$uid'";
            $row = $dbLink->exec($sql);
            if ($row) {
                $redis->hMSet($token, ['cdk' => $cdk, 'is_reveive_cdk' => 1]);
                return ['res' => 0, 'msg' => '领取成功!', ['cdk' => $cdk]];
            }
            throw new \PDOException('您已经领取过了！');
        } catch (\PDOException $e) {
            $redis->sRem($totalReveiveKey, $user['uid']);
            return ['res' => -1, 'msg' => '领取异常!' . $e->getMessage()];
        }
    }


    /**
     * 获取截止到当前cdk总的应发放数量
     * @param $totalKey
     * @return bool|float|int|mixed|string
     */
    public static function getCdkTotalNum()
    {
        $totalKey = 'TOTAL_CDK_NUM:' . date('Y-m-d');
        $redis = RedisClientLogic::getInstance();
        $totalNum = $redis->get($totalKey);
        if (!$totalNum) {
            $startdate = strtotime(ACTIVITY_SART_TIME);
            $enddate = strtotime(date('Y-m-d'));
            $days = round(($enddate - $startdate) / 3600 / 24);
            $totalNum = $days * PER_DAY_CDK_NUM;
            $redis->setex($totalKey, 86400, $totalNum);
        }
        return $totalNum;
    }


    /**
     * 生成CDK字符串
     * @return string
     * @throws \Exception
     */
    public static function createCdkString()
    {
        $length = 32;
        $string = '';
        while (($len = strlen($string)) < $length) {
            $size = $length - $len;

            $bytes = random_bytes($size);

            $string .= substr(str_replace(['/', '+', '='], '', base64_encode($bytes)), 0, $size);
        }
        return $string;
    }

    /**
     * 获取该登录用户收到的点赞数
     * @param $wishId
     * @return int
     */
    public static function getUserReveivePraiseNum($wishId)
    {
        $redis = RedisClientLogic::getInstance();
        return $wishId ? $redis->sCard(PER_WISHTID_RECEIVE_PRAISE_LIST . ":" . $wishId) : 0;
    }

    /**
     * 获取该登录用户给出的点赞数
     * @param $uid
     * @return int|string
     */
    public static function getUserProvideDianZanNum($uid)
    {
        $redis = RedisClientLogic::getInstance();
        return $redis->hGet(TOTAL_MY_DIANZAN, $uid) ? $redis->hGet(TOTAL_MY_DIANZAN, $uid) : 0;
    }
}